import { DOOR_STATES } from '@/constants/Command'
import type { BaseController } from '@/controller/BaseAppliance/definition'
import {
  confirmToControlLevelTips,
  showChildLockEnabledModal,
  showDoorOpenedRemoteStartDisabledModal,
  showLocalOperatingModal,
  showNoProgramModal,
  showOrderNotSupported,
  triggerGeneralControlNotActiveModal,
  triggerOfflineModal,
  triggerRemoteStartNotActiveModal,
} from './errorNotice'
import { useAccountStore } from '@/store/account'
import store from '@/store'
import { showModal } from '@/utils/mpHelper'
import { ValleyTimeOrder } from '@/constants/UniEventKeys'
import i18n from '@/i18n'
import { trackEvent, TrackType } from '@/dataReport/tracks'
import { safeTrack } from '@/dataReport/dataReportUtil'
import { useControlState } from '@/controller/BaseAppliance/useControl'
import { orderPermanentInfo } from '@/utils/deviceMessageSubscribe/deviceMessage'

const accountStore = useAccountStore(store)

/**
 * 详情页 电源开关的前置检查
 */
export function checkTogglePowerAccessable(control: BaseController.Control): boolean {
  return checkRemoteControl(control)
}

/**
 * 详情页 调节参数的前置检查
 *
 *  - 报错1：家电离线
 *  - 报错2：远程操作未打开
 *  - 报错3：家电被本地控制
 *  - 报错4：家电关机
 *  - 报错7：未选中程序
 *  - (不判断) 报错8：选中程序不支持预约启动
 */
export function checkAdjustAccessable(control: BaseController.Control) {
  // 虚拟家电跳过检查
  if (control.store.isVirtualAppliance) return true

  // 报错1：家电离线
  if (!checkOnlineState(control)) return false

  // 报错2：远程操作未打开
  if (!checkRemoteControl(control)) return false

  // 报错3：家电被本地控制
  if (!checkLocalOperating(control)) return false

  // 报错4：家电关机【洗碗机等家电待机情况下可以正常启动程序 无法拦截】

  // 报错7：未选中程序
  if (!checkProgramSelected(control)) return false

  // 其余场景 由接口报错触发报错 不再拦截
  return true
}

/**
 * 详情页 程序启动/预约下发前的通用前置检查
 *
 *  - 报错1：家电离线
 *  - 报错2：远程操作未打开
 *  - 报错3：家电被本地控制
 *  - 报错4：家电关机
 *  - 报错5：家电远程启动未打开
 *  - 报错6：洗衣机、洗碗机门未关
 *  - 报错7：未选中程序
 */
export function checkProgramAccessable(control: BaseController.Control) {
  // 虚拟家电跳过检查
  if (control.store.isVirtualAppliance) return true

  // 报错1：家电离线
  if (!checkOnlineState(control)) return false

  // 报错2：远程操作未打开
  if (!checkRemoteControl(control)) return false

  // 报错3：家电被本地控制
  if (!checkLocalOperating(control)) return false

  // 报错4：家电关机【洗碗机等家电待机情况下可以正常启动程序 无法拦截】

  // 报错5：家电远程启动未打开
  if (!checkRemoteStart(control)) return false

  // 报错7：未选中程序
  if (!checkProgramSelected(control)) return false

  // 其余场景 由接口报错触发报错 不再拦截
  return true
}

/**
 * 详情页 程序启动的前置检查
 *
 *  - 报错1：家电离线
 *  - 报错2：远程操作未打开
 *  - 报错3：家电被本地控制
 *  - 报错4：家电关机
 *  - 报错5：家电远程启动未打开
 *  - 报错6：洗衣机、洗碗机门未关
 *  - 报错7：未选中程序
 *
 *  - (不判断) 报错8：选中程序不支持预约启动
 *  - 报错9：童锁已打开
 */
export function checkStartProgramAccessable(control: BaseController.Control) {
  // 虚拟家电跳过检查
  if (control.store.isVirtualAppliance) return true

  // 程序启动的前置检查
  if (!checkProgramAccessable(control)) return false

  // 报错9：童锁已打开
  if (!checkChildLock(control)) return false

  // 其余特殊处理
  if (!checkSpecialAccessable(control, 'programAccessable')) return false

  // 其余场景 由接口报错触发报错 不再拦截
  return true
}

/**
 * 详情页 程序暂停的前置检查
 *
 *  - 报错9：童锁已打开
 */
export function checkPauseAccessable(control: BaseController.Control) {
  // 虚拟家电跳过检查
  if (control.store.isVirtualAppliance) return true

  // 报错9：童锁已打开
  if (!checkChildLock(control)) return false

  // 其余场景 由接口报错触发报错 不再拦截
  return true
}

/**
 * 详情页 程序继续的前置检查
 *
 *  - 报错9：童锁已打开
 */
export function checkResumeAccessable(control: BaseController.Control) {
  return checkPauseAccessable(control)
}

/**
 * 详情页 程序停止的前置检查
 *
 *  - 报错9：童锁已打开
 */
export function checkAbortAccessable(control: BaseController.Control) {
  // 虚拟家电跳过检查
  if (control.store.isVirtualAppliance) return true

  // 报错9：童锁已打开
  if (!checkChildLock(control)) return false

  // 其余场景 由接口报错触发报错 不再拦截
  return true
}

/**
 * 详情页 程序启动的谷电时间检查
 */
// 谷电提醒时间范围
const ValleyTipsRange = 3600 // 1小时 3600秒

export async function checkValleyTimeAccessable(
  control: BaseController.Control,
  options?: {
    onAccessable?: () => Promise<void>
  }
): Promise<boolean> {
  // 虚拟家电 跳过检查
  if (control.store.isVirtualAppliance) return true

  // 无需检查的品类 跳过检查
  if (!control.store.shouldCheckValleyTimeApproching) {
    await options?.onAccessable?.()
    return true
  }

  // 未设置谷电时间 跳过检查
  if (!accountStore.isSetValleyTime) {
    await options?.onAccessable?.()
    return true
  }

  /**
   * 计算谷电时间
   */
  // 谷电时分
  const [valleyHourText, valleyMinuteText] = accountStore.valleyElecStartTime.split(':')
  const valleyHour = parseInt(valleyHourText)
  const valleyMinute = parseInt(valleyMinuteText)

  // 当前时分
  const currentDate = new Date()
  const currentHour = currentDate.getHours()
  const currentMinute = currentDate.getMinutes()
  const currentTime = currentHour * 3600 + currentMinute * 60

  // 是否接近谷电时间 (未到谷电时间范围内 但接近范围)
  let almostInValleyTime = false

  /**
   * 当前时间是否小于今日谷电时间
   */
  const todayValleyTime = valleyHour * 3600 + valleyMinute * 60
  const todayDiffTime = todayValleyTime - currentTime
  almostInValleyTime = todayDiffTime > 0 && todayDiffTime <= ValleyTipsRange

  // 当前时间大于谷电时间 额外判断次日
  if (!almostInValleyTime) {
    const nextDayValleyTime = todayValleyTime + 86400
    const nextDayDiffTime = nextDayValleyTime - currentTime
    almostInValleyTime = nextDayDiffTime > 0 && nextDayDiffTime <= ValleyTipsRange
  }

  // 不在谷电时间范围内
  if (!almostInValleyTime) {
    await options?.onAccessable?.()
    return true
  }

  /**
   * 弹框提示
   */
  try {
    await showModal(
      {
        content: i18n.global.t('Appliance.StartProgram.ValleyTimeOrder.Modal.Content'),
        confirmText: i18n.global.t('Appliance.StartProgram.ValleyTimeOrder.Modal.Confirm.Text'),
        cancelText: i18n.global.t('Appliance.StartProgram.ValleyTimeOrder.Modal.Cancel.Text'),
        confirmColor: '#007AFF',
        cancelColor: '#666666',
      },
      {
        onCancel: async () => {
          await options?.onAccessable?.()
        },
      }
    )
    safeTrack(() => {
      let key = control.store.currentProgram?.key
      let name = control.store.currentProgram?.name
      trackEvent(
        'make_an_appointment',
        {
          program_key: key,
          program_name: name,
        },
        TrackType.ApplianceDetail,
        'Appliance.StartProgram.ValleyTimeOrder.Modal.Confirm.Text'
      )
    })

    // 用户点击确认 打开预约弹框 终止执行立即启动
    uni.$emit(ValleyTimeOrder)
    return false
  } catch (e) {
    console.error(e)
    // 用户点击取消 继续执行立即启动
    safeTrack(() => {
      let key = control.store.currentProgram?.key
      let name = control.store.currentProgram?.name
      trackEvent(
        'Appliance.StartProgram.ValleyTimeOrder.Modal.Cancel.Text',
        {
          program_key: key,
          program_name: name,
        },
        TrackType.ApplianceDetail
      )
    })

    return true
  }
}

/**
 * 详情页 点击Flex Area中与家电关联的前置检查
 *
 *  - 报错1：家电离线
 *  - 报错2：远程操作未打开
 *  - 报错3：家电被本地控制
 */
// 详情页 进入预约时间的前置检查
export function checkApplianceRelatedFlexAreaAccessable(control: BaseController.Control) {
  // 虚拟家电跳过检查
  if (control.store.isVirtualAppliance) return true

  // 报错1：家电离线
  if (!checkOnlineState(control)) return false

  // 报错2：远程操作未打开
  if (!checkRemoteControl(control)) return false

  // 报错3：家电被本地控制
  if (!checkLocalOperating(control)) return false

  return true
}

/**
 * 详情页 进入预约时间的前置检查
 *
 *  - 报错1：家电离线
 *  - 报错2：远程操作未打开
 *  - 报错3：家电被本地控制
 *  - 报错4：家电关机
 *  - 报错5：家电远程启动未打开
 *  - 报错6：洗衣机、洗碗机门未关
 *  - 报错7：未选中程序
 *  - 报错8：选中程序不支持预约启动
 *  - 报错9：童锁已打开
 */
// 详情页 进入预约时间的前置检查
export function checkOrderTimeAccessable(control: BaseController.Control) {
  // 虚拟家电跳过检查
  if (control.store.isVirtualAppliance) return true

  // 程序启动的前置检查
  if (!checkProgramAccessable(control)) return false

  // 报错8：选中程序不支持预约启动
  if (control.store.orderRelativeOption === null) {
    showOrderNotSupported()
    return false
  }

  // 报错9：童锁已打开
  if (!checkChildLock(control)) return false

  return true
}

/**
 * 详情页 进入预约时间的前置检查
 *
 *  - 报错1：家电离线
 *  - 报错2：远程操作未打开
 *  - 报错3：家电被本地控制
 *  - 报错4：家电关机
 *  - 报错5：家电远程启动未打开
 *  - 报错6：洗衣机、洗碗机门未关
 *  - 报错7：未选中程序
 *  - 报错8：选中程序不支持预约启动
 *  - 报错9：童锁已打开
 */
// 详情页 进入预约时间的前置检查
export function checkOrderProgramAccessable(control: BaseController.Control) {
  // 虚拟家电跳过检查
  if (control.store.isVirtualAppliance) return true

  // 程序启动的前置检查
  if (!checkOrderTimeAccessable(control)) return false

  // 报错9：童锁已打开
  if (!checkChildLock(control)) return false

  // 其余特殊处理
  if (!checkSpecialAccessable(control, 'orderAccessable')) return false

  return true
}

/**
 * Validation methods
 */
// 报错1：家电离线
function checkOnlineState(control: BaseController.Control): boolean {
  const isOnline = control.store.isOffline !== true
  if (!isOnline) triggerOfflineModal()
  return isOnline
}
// 报错2：远程操作未打开
function checkRemoteControl(control: BaseController.Control): boolean {
  if (control.store.remoteControl) return true

  // 判断是否需要跳转到远程控制等级 (SMM洗碗机特殊处理部分)
  if (control.store.showControlLevelTipsOnRemoteControlError) {
    confirmToControlLevelTips(control.store._datasource)
  }
  // 其他情况 弹出通用提示框：远程控制未开启
  else {
    triggerGeneralControlNotActiveModal()
  }
  return false
}
// 报错3：家电被本地控制
function checkLocalOperating(control: BaseController.Control): boolean {
  const { localOperating } = control.store
  if (localOperating) showLocalOperatingModal()
  return !localOperating
}
// 报错4：家电关机【洗碗机等家电待机情况下可以正常启动程序 无法拦截】
// function checkPowerOn(control: BaseController.Control): boolean {}
// 报错5：家电远程启动未打开
function checkRemoteStart(control: BaseController.Control): boolean {
  if (control.store.remoteStart) return true

  // 报错6：洗衣机、洗碗机门未关
  const isDoorOpened = control.store.doorState === DOOR_STATES.OPEN
  if (isDoorOpened) {
    // 门打开 特殊处理 弹出提示 (不使用Action Info的弹框)
    showDoorOpenedRemoteStartDisabledModal()
  } else {
    // 门处于关闭状态
    triggerRemoteStartNotActiveModal()
  }

  return false
}
// 报错7：未选中程序
function checkProgramSelected(control: BaseController.Control): boolean {
  if (control.store.currentProgramKey) return true

  showNoProgramModal()
  return false
}
// 报错9：童锁已打开
function checkChildLock(control: BaseController.Control): boolean {
  const { childLockActived } = useControlState(control)
  if (!childLockActived.value) return true

  showChildLockEnabledModal()
  return false
}
// 特殊报错判断
function checkSpecialAccessable(
  control: BaseController.Control,
  type: 'programAccessable' | 'orderAccessable'
): boolean {
  let accessable = true
  try {
    const checkResult = control.store.specialAccessableCheck?.(type)
    if (typeof checkResult === 'boolean') {
      accessable = checkResult
    }
  } catch (e) {
    console.error(e)
  }
  return accessable
}
